package utils

import (
	"fmt"
	"github.com/jlaffaye/ftp"
	"io"
	"log"
	"os"
	"strings"
	"time"
)

//连接的配置
type FtpClientConfig struct {
	Host     string          //ip
	Port     int64           // 端口
	Username string          //用户名
	Password string          //密码
	Conn     *ftp.ServerConn //ftp 连接
}

func (m *FtpClientConfig) CreateConn(host string, port int64, username, password string) {
	var (
		Conn *ftp.ServerConn //ftp 连接
		err  error
	)
	m.Host = host
	m.Port = port
	m.Username = username
	m.Password = password
	addr := fmt.Sprintf("%s:%d", m.Host, m.Port)
	if Conn, err = ftp.Dial(addr, ftp.DialWithTimeout(5*time.Second)); err != nil {
		log.Fatalln("连接发生错误:", err)
	}
	m.Conn = Conn
	if err = m.Conn.Login(username, password); err != nil {
		log.Fatalln("登录发生错误:", err)
	}
}

// EntryHandler 遍历ftp目录时的文件handler
// EntryHandler ...
type EntryHandler func(e *ftp.Entry, currentPath string) error

// FtpSource FTP 文件对象
type FtpSource struct {
	// ftp库的entry对象
	Entry *ftp.Entry
	// 文件的全路径+文件名
	Path string
}

// 遍历ftp目录，获取文件
func (m *FtpClientConfig) Walk(rootDir string, handler EntryHandler) error {
	entries, err := m.Conn.List(rootDir)
	if err != nil {
		return err
	}
	for _, entry := range entries {
		if entry.Name == "DVRWorkDirectory" {
			continue
		}
		switch entry.Type {
		case ftp.EntryTypeFile:
			handler(entry, rootDir)
		case ftp.EntryTypeFolder:
			m.Walk(fmt.Sprintf("%s/%s", rootDir, entry.Name), handler)
		default:
		}
	}
	return nil
}

func (m *FtpClientConfig) Listfiles(rootDir string) ([]*FtpSource, error) {
	FtpSources := []*FtpSource{}
	err := m.Walk(rootDir, func(entry *ftp.Entry, currentPath string) error {
		FtpSources = append(FtpSources, &FtpSource{
			Entry: entry,
			Path:  fmt.Sprintf("%s/%s", currentPath, entry.Name),
		})
		return nil
	})
	if err != nil {
		return nil, err
	}
	return FtpSources, nil
}

// 下载文件夹
func (ftpSourceManager *FtpClientConfig) DownloadDir(FtpPath, TargetPath string) error {
	walker := ftpSourceManager.Conn.Walk(FtpPath)
	for walker.Next() {
		local := strings.Replace(walker.Path(), FtpPath, TargetPath, 1)
		if walker.Stat().Type == ftp.EntryTypeFolder {
			os.MkdirAll(local, 0777)
		} else {
			func() error {
				time1 := time.Now() // 当前时间点
				f, err := os.OpenFile(local, os.O_RDWR|os.O_CREATE, 0777)
				if err != nil {
					fmt.Println("Create File error", err)
					return err
				}
				defer f.Close()
				r, err := ftpSourceManager.Conn.Retr(walker.Path())
				if err != nil {
					fmt.Println("Get Ftp File error", err)
					return err
				}
				defer r.Close()
				io.Copy(f, r)
				time2 := time.Now() // 当前时间点
				subTime := time2.Sub(time1).Seconds()
				fmt.Printf("下载文件%s，时间差：%fs \n", local, subTime)
				return nil
			}()
		}
	}
	return nil
}
